package com.lwj.charts.commonutils;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.concurrent.CopyOnWriteArraySet;

@Slf4j
@Component
@ServerEndpoint(value = "/websocket/{id}",encoders = {ServerEncoder.class})
public class WebSocketServer{
    //在线连接数,应该把它设计成线程安全的
    private static int onlineCount = 0;

    @Autowired
    private static SendMessageSercice sendMessageSercice;
    @Autowired
    public void setSendMessageSercice(SendMessageSercice sendMessageSercice){
        this.sendMessageSercice = sendMessageSercice;
    }
    //concurrent包的线程安全Set，用来存放每个客户端对应的MyWebSocket对象。
    //虽然@Component默认是单例模式的，但springboot还是会为每个websocket连接初始化一个bean，所以可以用一个静态set保存起来。
    public static CopyOnWriteArraySet<WebSocketServer> webSocketSet
            = new CopyOnWriteArraySet<>();
    //与某个客户端的连接会话，需要通过它来给客户端发送数据
    private Session session;

    //会话窗口的ID标识
    private String id = "";

    /**
     * 链接成功调用的方法
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("id") String id) {
        log.info("onOpen >> 链接成功");
        this.session = session;
        //将当前websocket对象存入到Set集合中
        webSocketSet.add(this);
        //在线人数+1
        addOnlineCount();
        log.info("有新窗口开始监听：" + id + ", 当前在线人数为：" + getOnlineCount());
        this.id = id;
//        sendMessageSercice = applicationContext.getBean(SendMessageSercice.class);
        try {
//            sendMessage("有新窗口开始监听：" + id + ", 当前在线人数为：" + getOnlineCount());
            sendMessageSercice.sendDataToWeb();
        } catch (Exception e) {
            log.error(e.toString());
        }


    }
    /**
     * 链接关闭调用的方法
     */
    @OnClose
    public void onClose() {
        log.info("onClose >> 链接关闭");
        //移除当前Websocket对象
        webSocketSet.remove(this);
        //在内线人数-1
        subOnLineCount();
        log.info("链接关闭，当前在线人数：" + getOnlineCount());
    }
    /**
     * 收到客户端消息后调用的方法
     *
     * @param message
     * @param session
     */
    @OnMessage
    public void onMessage(String message, Session session) {
        log.info("接收到窗口：" + id + " 的信息：" + message);

        //发送信息
        for (WebSocketServer item : webSocketSet) {
            try {
                item.sendMessage("接收到窗口：" + id + " 的信息：" + message);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    @OnError
    public void onError(Session session, Throwable e) {
        e.printStackTrace();
    }
    /**
     * 推送消息
     *
     * @param message
     */
    private  void sendMessage(String message) throws IOException {
        this.session.getBasicRemote().sendText(message);
    }
    private void sendObject(Object object) throws IOException, EncodeException {
        this.session.getBasicRemote().sendObject(object);
    }
//　*　id为null时是群发
//     * @param map
//     * @param id
//     */
    public static void sendData(String id, Object map) {
        for (WebSocketServer item : webSocketSet) {
            try {
                if (id == null) {
                    item.sendObject(map);
                } else if (item.id.equals(id)) {
                    item.sendObject(map);
                }
            } catch (Exception e) {
                e.printStackTrace();
                continue;
            }
        }
    }
    private void subOnLineCount() {
        WebSocketServer.onlineCount--;
    }

    public static synchronized int getOnlineCount() {
        return onlineCount;
    }

    private void addOnlineCount() {
        WebSocketServer.onlineCount++;
    }

}


